#include "../StdAfx.h"
#include "../ComPropVariant.h"
#include "Factory.h"

using namespace SevenZip;

STDMETHODIMP SevenZip::CSevenZipMethod::Initialize(CSevenZipLibraryPtr & Lib, UINT32 Index)
{
	HRESULT hr;

	if (SUCCEEDED(hr = Lib->GetMethodPropertyAsCLSID(Index, PROPID_Encoder, EncoderClassID)))
	{
		if (SUCCEEDED(hr = Lib->GetMethodPropertyAsCLSID(Index, PROPID_Decoder, DecoderClassID)))
		{
			hr = Lib->GetMethodPropertyAsString(Index, PROPID_Name, Name);
		}
	}

	return hr;
}

STDMETHODIMP SevenZip::CSevenZipFormat::Initialize(CSevenZipLibraryPtr & Lib, UINT32 Index)
{
	HRESULT  hr;
	CStringW tmp;

	if (SUCCEEDED(hr = Lib->GetFormatPropertyAsCLSID(Index, PROPID_ClassID, _ClassID)))
	{
		if (SUCCEEDED(hr = Lib->GetFormatPropertyAsString(Index, PROPID_Name, _Name)))
		{
			if (S_OK == (hr = Lib->GetFormatPropertyAsString(Index, PROPID_Extension, tmp)))
			{
				_Library = Lib;
				_Extensions.Add(tmp);

				if (S_OK == (hr = Lib->GetFormatPropertyAsString(Index, PROPID_AddExtension, tmp)))
				{
					_Extensions.Add(tmp);
				}
			}
		}
	}

	return hr;
}

STDMETHODIMP SevenZip::CSevenZipFormat::MatchesExtension(LPCWSTR Extension) CONST
{
	for (size_t i = 0; i < _Extensions.GetCount(); i++)
	{
		const CStringW & ext = _Extensions.GetAt(i);

		if (ext.CompareNoCase(Extension) == 0)
		{
			return S_OK;
		}
	}

	return S_FALSE;
}

STDMETHODIMP SevenZip::CSevenZipFactory::FindFormatByExtension(LPCWSTR Extension, CAtlArray<const CSevenZipFormat*> & Results) CONST
{
	if ((Extension != NULL) && (*Extension == L'.'))
	{
		++Extension;
	}

	if ((Extension == NULL) || (*Extension == L'\0'))
	{
		return E_INVALIDARG;
	}

	for (size_t i = 0; i < _Formats.GetCount(); i++)
	{
		const CSevenZipFormat & f = _Formats.GetAt(i);

		if (f.MatchesExtension(Extension) == S_OK)
		{
			Results.Add(&f);
		}
	}

	return S_OK;
}

STDMETHODIMP SevenZip::CSevenZipFactory::AddLibrary(LPCWSTR LibPath)
{
	HRESULT hr;
	CSevenZipLibraryPtr Lib;

	if (SUCCEEDED(hr = CoCreate(Lib)))
	{
		if (SUCCEEDED(hr = Lib->SetPath(LibPath)))
		{
			hr = AddLibrary(Lib);
		}
	}

	return hr;
}

STDMETHODIMP SevenZip::CSevenZipFactory::AddLibrary(CSevenZipLibraryPtr & Library)
{
	//HRESULT hr;

	//if (SUCCEEDED(hr = AddMethods(Library)))
	//{
	//	hr = AddFormats(Library);
	//}

	return AddFormats(Library);
}

STDMETHODIMP SevenZip::CSevenZipFactory::AddMethods(CSevenZipLibraryPtr & Library)
{
	UINT32  Added;
	HRESULT hr = Library->GetMethodCount(&Added);

	if (SUCCEEDED(hr) && (Added > 0))
	{
		size_t OldCount = _Methods.GetCount();

		if (!_Methods.SetCount(OldCount + Added))
		{
			return E_OUTOFMEMORY;
		}

		for (UINT32 i = 0; SUCCEEDED(hr) && (i < Added); i++)
		{
			hr = _Methods.GetAt(OldCount + i).Initialize(Library, i);
		}
	}
	
	return hr;
}
STDMETHODIMP SevenZip::CSevenZipFactory::AddFormats(CSevenZipLibraryPtr & Library)
{
	UINT32  Added;
	HRESULT hr = Library->GetFormatCount(&Added);
	 
	if (SUCCEEDED(hr) && (Added > 0))
	{
		size_t OldCount = _Formats.GetCount();

		if (!_Formats.SetCount(OldCount + Added))
		{
			return E_OUTOFMEMORY;
		}

		for (UINT32 i = 0; SUCCEEDED(hr) && (i < Added); i++)
		{
			hr = _Formats.GetAt(OldCount + i).Initialize(Library, i);
		}
	}

	return hr;
}
